﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using V2TEK.NET.SH.Silverlight.Charts.GanttHelper;
using System.Xml.Linq;
using V2TEK.NET.SH.Silverlight.GanttView.SharePointLists;
using System.Collections.Generic;
using System.Linq;
using V2TEK.NET.SH.Silverlight.Charts.Core.Schedule;
using System.Text.RegularExpressions;
using System.IO;
using V2TEK.NET.SH.Silverlight.Charts.TreeGridHelper;

namespace V2TEK.NET.SH.Silverlight.GanttView
{
    public class DataManagerBase:DependencyObject
    {
        /// <summary>
        /// 根目录的 FileRef 级数 701;#sites/project1/Lists/Schedule/详设总计划 这个为 5
        /// </summary>
        protected int rootForderLevelNum = 5;

        public string IDFIELD = "ows_ID";
        public string TASKNAMEFIELD = "ows_LinkTitle";
        public string STARTDATEFIELD = "ows_PlanCD";
        public string ENDDATEFIELD = "ows_PlanSD";
        public string REQUIRETIMEFIELD = "ows_WorkDuration";
        public string PERCENTCOMPLETEFIELD = "ows_PercentComplete";

        public static string PARENTSCHEDULELINKFIELD = "ows_ParentScheduleLink";
        public static string SSZRCIDSTOREFIELD = "PARENTSCHEDULEID";

        public string[] KnownFieldNames = new string[] { "ows_ID", "LinkTitle", "PlanCD", "PlanSD", "WorkDuration", "PercentComplete" };

        /// <summary>
        /// 视图字段信息
        /// </summary>
        public virtual XElement ViewFieldXml { get; set; }
        /// <summary>
        /// 视图数据信息
        /// </summary>
        public virtual XElement ViewDataXml { get; set; }

        protected CommonCalendar mCalendar = new CommonCalendar();

        public virtual void SetFields(params string[] paras)
        {
            IDFIELD = "ows_" + paras[0];
            TASKNAMEFIELD = "ows_" + paras[1];
            STARTDATEFIELD = "ows_" + paras[2];
            ENDDATEFIELD = "ows_" + paras[3];
            PERCENTCOMPLETEFIELD = "ows_" + paras[4];

            KnownFieldNames = new[] { IDFIELD.Substring(4), 
                TASKNAMEFIELD.Substring(4), 
                STARTDATEFIELD.Substring(4),
                ENDDATEFIELD.Substring(4), 
                REQUIRETIMEFIELD.Substring(4), 
                PERCENTCOMPLETEFIELD.Substring(4) };
        }

        public virtual Dictionary<string, SharePointField> Fields
        {
            get;
            set;
        }

        public virtual List<string> ViewFields { get; set; }

        protected GeneralPropertyDependecy mGeneralDependecy = new GeneralPropertyDependecy();

        public virtual ObservableCollection<ITaskDescriptor> Data
        {
            get;
            set;
        }

        public virtual event EventHandler GetDataCompleted;


        protected virtual void ParseFields(XElement node, Dictionary<string, SharePointField> fields, List<string> viewFields)
        {

            foreach (XElement ele in node.Elements())
            {
                if (ele.Name.LocalName == "Field")
                {
                    string name = GetXElementAttribute(ele, "Name");
                    if (!KnownFieldNames.Contains(name))
                    {
                        string displayName = GetXElementAttribute(ele, "DisplayName");
                        string type = GetXElementAttribute(ele, "Type");
                        SharePointField field = new SharePointField();
                        switch (type)
                        {
                            case "Number":
                                break;
                            case "DateTime":
                                break;
                            case "Choice":
                            case "ModStat":
                                type = "Choice";
                                field.Choice = new Dictionary<string, string>();
                                ParseChoice(ele, field);
                                break;
                            case "LookupWithPicker":
                                type = "LookupWithPicker";
                                break;
                            default:
                                type = "String";
                                break;
                        }

                        field.Name = "ows_" + name;
                        field.DisplayName = displayName;
                        field.FieldType = type;

                        if (!fields.ContainsKey(name))
                            fields.Add(name, field);
                    }
                }
                else if (ele.Name.LocalName == "FieldRef")
                {
                    string name = GetXElementAttribute(ele, "Name");
                    if (!KnownFieldNames.Contains(name))
                    {
                        viewFields.Add(name);
                    }
                }
                else
                {
                    ParseFields(ele, fields, viewFields);
                }
            }
        }

        protected virtual void ParseChoice(XElement node, SharePointField field)
        {
            int i = 0;
            foreach (XElement ele in node.Elements())
            {
                if (ele.Name.LocalName == "CHOICE")
                {
                    string[] temp = ele.Value.Split('#');
                    field.Choice.Add(i.ToString(), temp[temp.Length - 1]);
                    i++;
                }
                else if (ele.Name.LocalName == "Default")
                {
                    field.ChoiceDefault = ele.Value;
                }
                else
                {
                    ParseChoice(ele, field);
                }
            }
        }


        public virtual void GetZrcChild(string listName, string viewName, AbstractExpander expander)
        {
            if (expander is DynamicTaskExpander)
            {
                DynamicTaskExpander dyExpander = expander as DynamicTaskExpander;
                if (dyExpander.IsLoading)
                    return;
                ITaskDescriptor task = (expander.Data as TaskEntryLayoutItem).Data as ITaskDescriptor;
                if (task.Children.Count > 0)
                    return;
                string zrcID = task.UniqueId.ToString();
                if (!string.IsNullOrWhiteSpace(zrcID))
                {
                    GetData(listName, viewName, zrcID.Trim(), dyExpander);
                }
                else
                {
                    dyExpander.HideExpander();
                }
            }
        }

        /// <summary>
        /// 根据总计划ID获取数据
        /// </summary>
        /// <param name="listName"></param>
        /// <param name="viewName"></param>
        /// <param name="zrcID"></param>
        public virtual void GetData(string listName, string viewName, string zrcID, DynamicTaskExpander expander)
        {
            if (expander.IsLoading)
                return;

            var client = ServiceManager.GetShartPointListsService();
            var xquery = XElement.Parse(@"<Query>
   <Where>
    <And>
      <Eq>
         <FieldRef Name=""_ModerationStatus"" />
         <Value Type=""Text"">已批准</Value>
      </Eq>
    <Eq>
        <FieldRef Name=""ParentScheduleLink"" LookupId=""TRUE"" />
        <Value Type=""Lookup"">" + zrcID + @"</Value>
    </Eq>
    </And>
   </Where>
</Query>");


            client.GetListItemsAsync(listName, viewName,
                          xquery,
                          null,
                          "0",
                          new XElement("QueryOptions",
                              new XElement("IncludeMandatoryColumns", false),
                              new XElement("DateInUtc", true),
                              XElement.Parse("<ViewAttributes Scope=\"RecursiveAll\" />")
                              ),
                          null,
                          expander
                          );

            client.GetListItemsCompleted += new EventHandler<GetListItemsCompletedEventArgs>(client_GetListItemsCompleted1);

            expander.BeginLoading();
        }

        protected virtual void client_GetListItemsCompleted1(object sender, GetListItemsCompletedEventArgs e)
        {
            DynamicTaskExpander expander = e.UserState as DynamicTaskExpander;
            if (e.Error == null)
            {
                var tasks = new ObservableCollection<ITaskDescriptor>();
                List<ITaskDescriptor> taskList = new List<ITaskDescriptor>();
                ParseListItems(e.Result, tasks, taskList);

                expander.Collapse();
                if (taskList.Count == 0)
                {
                    expander.HideExpander();
                }
                else
                {
                    ReSort(taskList);

                    ITaskDescriptor task = (expander.Data as TaskEntryLayoutItem).Data as ITaskDescriptor;
                    string wbs = task.WBS;
                    for (int i = 0; i < taskList.Count; i++)
                    {
                        var item = taskList[i];
                        item.EnableExpand = false;
                        item.TaskType = TaskType.Task;
                        item.WBS = wbs + "." + (i + 1).ToString();
                        task.Children.Add(item);
                        item.Parent = task;
                    }

                }
                expander.Collapse();
                expander.Expand();

            }

            expander.EndLoading();
        }

        public virtual void GetData(string listName, string viewName)
        {
            var client = ServiceManager.GetShartPointListsService();
            client.GetListAndViewAsync(listName, viewName);
            client.GetListAndViewCompleted += (sender, e) =>
                {
                    if (e.Error == null)
                    {
                        try
                        {
                            if (Fields == null)
                                Fields = new Dictionary<string, SharePointField>();
                            else
                                Fields.Clear();
                            if (ViewFields == null)
                                ViewFields = new List<string>();
                            else
                                ViewFields.Clear();
                            ViewFieldXml = e.Result;
                            ParseFields(e.Result, Fields, ViewFields);
                            var result = from c in Fields where ViewFields.Contains(c.Key) select c;
                            List<KeyValuePair<string, SharePointField>> list = new List<KeyValuePair<string, SharePointField>>(result);
                            Fields.Clear();
                            foreach (var item in list)
                            {
                                Fields.Add(item.Key, item.Value);
                            }
//                            var xquery = XElement.Parse(@"<Query>
//   <Where>
//      <Eq>
//         <FieldRef Name=""_ModerationStatus"" />
//         <Value Type=""Text"">已批准</Value>
//      </Eq>
//   </Where>
//</Query>");
                            var xquery = XElement.Parse(@"<Query>
   <Where>
    <And>
      <Eq>
         <FieldRef Name=""_ModerationStatus"" />
         <Value Type=""Text"">已批准</Value>
      </Eq>
    <IsNull>
      <FieldRef Name = ""ParentScheduleLink""/>
    </IsNull>
    </And>
   </Where>
</Query>");


                            client.GetListItemsAsync(listName, viewName,
                                          xquery,
                                          null,
                                          "0",
                                          new XElement("QueryOptions",
                                              new XElement("IncludeMandatoryColumns", false),
                                              new XElement("DateInUtc", true),
                                              XElement.Parse("<ViewAttributes Scope=\"RecursiveAll\" />")
                                              ),
                                          null
                                          );

                            client.GetListItemsCompleted += new EventHandler<GetListItemsCompletedEventArgs>(client_GetListItemsCompleted);
                        }
                        catch
                        {
                            this.Data = null;
                            this.Fields = null;
                            this.ViewFields = null;
                            RaiseGetDataCompleted();
                        }
                    }
                    else
                    {

                        this.Data = null;
                        this.Fields = null;
                        this.ViewFields = null;
                        RaiseGetDataCompleted();
                    }
                };
        }

        protected virtual void client_GetListItemsCompleted(object sender, GetListItemsCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                ParseDataXML(e.Result);
            }
            else
            {

                this.Data = null;
                this.Fields = null;
                this.ViewFields = null;
            }
            RaiseGetDataCompleted();
        }

        protected virtual void RaiseGetDataCompleted()
        {
            if (GetDataCompleted != null)
            {
                GetDataCompleted(this, EventArgs.Empty);
            }
        }

        protected virtual string GetXElementAttribute(XElement elem, string name)
        {
            XAttribute xa = elem.Attribute(name);
            if (xa == null)
                return null;
            else
                return xa.Value;
        }

        /// <summary>
        /// 重新生成WBS代码
        /// </summary>
        /// <param name="tasks"></param>
        protected virtual void UpdateParent(ObservableCollection<ITaskDescriptor> tasks)
        {
            foreach (var item in tasks)
            {
                if (item.Parent == null)
                {
                    item.WBS = (tasks.IndexOf(item) + 1).ToString();
                }
                else
                {
                    item.WBS = item.Parent.WBS + "." + (item.Parent.Children.IndexOf(item) + 1).ToString();
                }
                if (item.Children.Count == 0)
                {
                    this.UpdateTask(item);
                }
                else
                {
                    UpdateParent(item.Children);
                }
            }
        }


        public virtual void UpdateTask(ITaskDescriptor task)
        {
            if (task.Parent != null)
            {
                this.mGeneralDependecy.UpdateTask(task);
            }
        }

        /// <summary>
        /// 关联中短计划
        /// </summary>
        /// <param name="tasks"></param>
        /// <returns></returns>
        protected virtual ObservableCollection<ITaskDescriptor> ReBuild(ObservableCollection<ITaskDescriptor> tasks)
        {
            if (tasks.Count == 2)
            {
                //专业
                ObservableCollection<ITaskDescriptor> zrcTasks = tasks[0].Children;
                ITaskDescriptor[] zrcTasksList = new GanttOutput().GetTasks(zrcTasks, null);
                //中短计划任务
                ObservableCollection<ITaskDescriptor> xrcTasks = tasks[1].Children;
                //将专业的Parent去掉
                foreach (var item in zrcTasks)
                {
                    item.Parent = null;
                }
                //关联中短计划关系
                foreach (var item in xrcTasks)
                {
                    AddXrcParent(item, zrcTasksList);
                }

                return zrcTasks;
            }
            return tasks;
        }

        protected virtual void AddXrcParent(ITaskDescriptor task, ITaskDescriptor[] zrcTasks)
        {
            if (task.Children.Count == 0)
            {
                if (task.ExtendAttributes.ContainsKey(PARENTSCHEDULELINKFIELD))
                {
                    //根据所属总计划ID查找总计划，并将短计划关联
                    for (int i = 0; i < zrcTasks.Length; i++)
                    {
                        var parent = zrcTasks[i];
                        if (string.Equals(parent.UniqueId, task.ExtendAttributes[SSZRCIDSTOREFIELD]))
                        {
                            parent.Children.Add(task);
                            break;
                        }
                    }
                }
            }
            else
            {
                foreach (var item in task.Children)
                {
                    AddXrcParent(item, zrcTasks);
                }
            }
        }

        /// <summary>
        /// 根据日期排序
        /// </summary>
        /// <param name="tasks"></param>
        protected virtual void ReSort(ObservableCollection<ITaskDescriptor> tasks)
        {
            var rr = tasks.OrderBy(new Func<ITaskDescriptor, DateTime>(GetTaskStartDate));
            var r2 = rr.ToArray();
            tasks.Clear();
            for (int i = 0; i < r2.Length; i++)
            {
                var t = r2.ElementAt(i);
                tasks.Add(t);
            }

            foreach (var item in tasks)
            {
                ReSort(item.Children);

                if (item.Children.Count > 0)
                {
                    var result = item.Children.OrderBy(new Func<ITaskDescriptor, DateTime>(GetTaskStartDate));
                    var r = result.ToArray();
                    item.Children.Clear();
                    for (int i = 0; i < r.Length; i++)
                    {
                        var t = r.ElementAt(i);
                        item.Children.Add(t);
                    }
                }
            }
        }

        /// <summary>
        /// 根据日期排序
        /// </summary>
        /// <param name="tasks"></param>
        protected virtual void ReSort(List<ITaskDescriptor> tasks)
        {
            var rr = tasks.OrderBy(new Func<ITaskDescriptor, DateTime>(GetTaskStartDate));
            var r2 = rr.ToArray();
            tasks.Clear();
            for (int i = 0; i < r2.Length; i++)
            {
                var t = r2.ElementAt(i);
                tasks.Add(t);
            }

            foreach (var item in tasks)
            {
                ReSort(item.Children);

                if (item.Children.Count > 0)
                {
                    var result = item.Children.OrderBy(new Func<ITaskDescriptor, DateTime>(GetTaskStartDate));
                    var r = result.ToArray();
                    item.Children.Clear();
                    for (int i = 0; i < r.Length; i++)
                    {
                        var t = r.ElementAt(i);
                        item.Children.Add(t);
                    }
                }
            }
        }

        protected virtual DateTime GetTaskStartDate(ITaskDescriptor task)
        {
            return task.StartDate;
        }

        //class TaskStartDateCompare : IComparer<DateTime>
        //{

        //    public virtual int Compare(DateTime x, DateTime y)
        //    {
        //        if (x > y)
        //            return 1;
        //        if (x == y)
        //            return 0;
        //        return -1;
        //    }
        //}


        protected virtual void ParseDataXML(XElement xml)
        {
            ViewDataXml = xml;
            var tasks = new ObservableCollection<ITaskDescriptor>();
            List<ITaskDescriptor> taskList = new List<ITaskDescriptor>();
            ParseListItems(xml, tasks, taskList);
            RelinkTask(taskList, tasks);
            LinkXrcToZrc(taskList);
            ReSort(tasks);
            this.Data = tasks;
        }

        /// <summary>
        /// 连接短计划到总计划
        /// </summary>
        /// <param name="taskList"></param>
        protected virtual void LinkXrcToZrc(List<ITaskDescriptor> taskList)
        {
            var array = taskList.ToArray();
            foreach (var item in taskList)
            {
                if (item.Children.Count == 0)
                {
                    AddXrcParent(item, array);
                }
            }
        }

        /// <summary>
        /// 关联父子关系
        /// </summary>
        /// <param name="taskList"></param>
        /// <param name="tasks"></param>
        protected virtual void RelinkTask(List<ITaskDescriptor> taskList, ObservableCollection<ITaskDescriptor> tasks)
        {
            for (int i = 0; i < taskList.Count; i++)
            {
                var task = taskList[i];
                string fileRef = task.ExtendAttributes["FileRef"] as string;

                var fileRefList = fileRef.Split('/');
                if (fileRefList.Length == rootForderLevelNum)
                {
                    tasks.Add(task);
                }

                int pos = fileRef.LastIndexOf("/");
                string parentFileRef = fileRef.Substring(0, pos);
                for (int j = 0; j < i; j++)
                {
                    var parent = taskList[j];
                    if (string.Equals(parent.ExtendAttributes["FileRef"], parentFileRef))
                    {
                        parent.Children.Add(task);
                        parent.EnableExpand = true;
                        break;
                    }
                }

                if (task.Parent == null)
                {
                    task.WBS = tasks.Count.ToString();
                }
                else
                {
                    task.WBS = task.Parent.WBS + "." + task.Parent.Children.Count;
                }
            }
        }

        protected virtual void ParseListItems(XElement node, ObservableCollection<ITaskDescriptor> tasks, List<ITaskDescriptor> taskList)
        {
            foreach (XElement ele in node.Elements())
            {
                if (ele.Name.LocalName == "row")
                {
                    bool enableExpanded = ele.HasElements;
                    ITaskDescriptor task = new SimpleTaskDescriptor();
                    task.TaskType = TaskType.SummaryTask;
                    ((ITime1)task).Calendar = mCalendar;
                    task.ExtendAttributes = new Charts.Core.DependencyDictionary<string, object>();
                    string ows_FileRef = GetXElementAttribute(ele, "ows_FileRef");
                    task.ExtendAttributes["ows_FileRef"] = ows_FileRef;
                    string fileRef = ows_FileRef.Split(';')[1];
                    int pos = fileRef.LastIndexOf("/");
                    string parentFileRef = fileRef.Substring(0, pos);
                    task.ExtendAttributes["FileRef"] = fileRef;

                    task.TaskName = GetXElementAttribute(ele, TASKNAMEFIELD);
                    string start = GetXElementAttribute(ele, STARTDATEFIELD);
                    string end = GetXElementAttribute(ele, ENDDATEFIELD);
                    if (start != null)
                    {
                        task.StartDate = DateTime.Parse(start);
                        task.StartDate = new DateTime(task.StartDate.Year, task.StartDate.Month, task.StartDate.Day);
                    }
                    if (end != null)
                    {
                        task.EndDate = DateTime.Parse(end);
                        task.EndDate = new DateTime(task.EndDate.Year, task.EndDate.Month, task.EndDate.Day);
                    }
                    task.TotalMilliseconds = TimeSpan.FromDays(double.Parse(GetXElementAttribute(ele, REQUIRETIMEFIELD) ?? "0")).TotalMilliseconds;
                    task.PercentComplete = float.Parse(GetXElementAttribute(ele, PERCENTCOMPLETEFIELD) ?? "0") * 100;
                    task.UniqueId = GetXElementAttribute(ele, IDFIELD) ?? "";

                    foreach (var field in Fields.Values)
                    {
                        string temp = GetXElementAttribute(ele, field.Name);
                        if (temp != null)
                        {
                            if (!task.ExtendAttributes.ContainsKey(field.Name))
                            {
                                switch (field.FieldType)
                                {
                                    case "Number":
                                        task.ExtendAttributes.Add(field.Name, double.Parse(temp));
                                        break;
                                    case "DateTime":
                                        task.ExtendAttributes.Add(field.Name, DateTime.Parse(temp));
                                        break;
                                    case "Choice":
                                        if (field.Choice != null && field.Choice.ContainsKey(temp))
                                        {
                                            task.ExtendAttributes.Add(field.Name, field.Choice[temp]);
                                        }
                                        else
                                        {
                                            task.ExtendAttributes.Add(field.Name, field.ChoiceDefault);
                                        }
                                        break;
                                    case "LookupWithPicker":
                                        //string pattern = @"^(\d+;#(\w+))*$";
                                        //MatchCollection coll = Regex.Matches(temp.ToString(), pattern);
                                        string[] coll = temp.ToString().Split(new string[] { ";#" }, StringSplitOptions.None);
                                        temp = "";
                                        string sszrcID = "";
                                        for (int i = 0; i < coll.Length; i = i + 2)
                                        {
                                            sszrcID = coll[i];
                                            string item = coll[i + 1];
                                            if (!string.IsNullOrWhiteSpace(item))
                                            {
                                                temp = temp + item + ";";
                                            }
                                        }

                                        task.ExtendAttributes.Add(field.Name, temp.TrimEnd(';'));

                                        //构建所属总计划,将所属总计划ID写入到任务属性，以后会构建中短计划关系
                                        if (field.Name == PARENTSCHEDULELINKFIELD)
                                        {
                                            if (!string.IsNullOrWhiteSpace(sszrcID))
                                            {
                                                task.ExtendAttributes.Add(SSZRCIDSTOREFIELD, sszrcID);
                                                task.TaskType = TaskType.Task;

                                                App.Logs.Info(string.Format("task[{0}]有父节点ID[{1}]", task.TaskName, sszrcID));
                                            }
                                            else
                                            {
                                                task.TaskType = TaskType.SummaryTask;
                                            }
                                        }

                                        break;
                                    default:
                                        task.ExtendAttributes.Add(field.Name, temp.ToString());
                                        break;
                                }
                            }
                        }
                    }

                    taskList.Add(task);
                    mGeneralDependecy.Link(task);

                    if (enableExpanded)
                    {
                        ObservableCollection<ITaskDescriptor> _child = task.Children;
                        ParseListItems(ele, _child, taskList);
                    }
                }
                else
                {
                    ParseListItems(ele, tasks, taskList);
                }
            }
        }
    }

    public class SharePointField
    {
        public virtual string Name { get; set; }
        public virtual string DisplayName { get; set; }
        public virtual string FieldType { get; set; }

        public virtual Dictionary<string, string> Choice { get; set; }
        public virtual string ChoiceDefault { get; set; }

        public virtual string ShortName
        {
            get
            {
                if (Name != null && Name.Length > 4)
                    return Name.Substring(4);
                return "";
            }
        }
    }
}
